<template>
  <div id="data-table">
    <!--menu-->
    <div class="beetles_table_menu">
      <div class="beetles_table_left">
        <slot name="menuLeft"></slot>
      </div>
      <div class="beetles_table_right">
        <slot name="menuRight">
          <el-tooltip effect="dark" content="刷新" placement="top-start">
            <el-button size="small" circle @click="refreshChange" icon="el-icon-refresh"></el-button>
          </el-tooltip>
          <el-tooltip effect="dark" content="显隐" placement="top-start">
            <el-button size="small" circle @click="showHide" icon="el-icon-s-operation"></el-button>
          </el-tooltip>

        </slot>
      </div>
    </div>
    <!--表头浮动占位-->
    <div v-show="headerOut" id="header-seat" :style="{height:headerHeight + 'px',width:'100%'}"></div>
    <el-table :style="cssTop"
              :class="headerOut ? 'header-out':''"
              class="table"
              :header-cell-style="changeTableCell"
              id="beetles_table"
              ref="beetlesTable"
              :border="option.border"
              :data="list"
              style="width: 100%"
              @selection-change="selectionChange"
              @row-dblclick="rowDbclick"
              @row-click="rowClick"
              v-loading="tableLoading">
      <el-table-column v-if="option.selection" type="selection" width="55" fixed></el-table-column>
      <el-table-column v-if="option.index" label="#" type="index" width="50" align="center" fixed>
        <template scope="scope">
          <!-- 有分页时，序号显示 -->
          <span v-if="page">{{ (page.currentPage - 1) * page.pageSize + scope.$index + 1 }}</span>
          <!-- 无分页时，序号显示 -->
          <span v-else>{{ scope.$index + 1 }}</span>
        </template>
      </el-table-column>
      <template v-for="(col, index) in option.column">
        <el-table-column :key="index"
                         min-width="80px"
                         v-if=" columnShow(col) && !col.hide"
                         :prop="col.prop" :label="col.label"
                         :fixed="col.fixed"
                         :width="col.width"
                         :formatter="col.formatter"
                         :render-header="col.renderHeader"
        >
          <template slot="header" slot-scope="scope">
            <tooltip-text :content="col.label"></tooltip-text>
          </template>
          <!-- 操作列/自定义列 -->
          <slot :name="col.prop" :row="scope.row" slot-scope="scope">
            <div style="width: 100%">
              <tooltip-text v-if="col.type" :content="translate(scope.row,col)"></tooltip-text>
              <tooltip-text v-else :content="scope.row[col.prop]"/>
            </div>
          </slot>
        </el-table-column>
      </template>
      <el-table-column v-if="option.menu || true" label="操作" align="center" fixed="right"
                       :width="option.menuWidth?option.menuWidth:120">
        <slot name="menu" :row="scope.row" slot-scope="scope"></slot>
      </el-table-column>
    </el-table>
    <!-- 是否调用分页 -->
    <el-pagination
      v-if="page"
      :style="pageWidth"
      ref="pagination"
      background
      :class="pageOut ? 'beetles_table_out_page':'beetles_table_page'"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="tablePage.currentPage"
      :page-size="tablePage.pageSize"
      :page-sizes="tablePage.pageSizes||[10,15,20,30,40,50,100,200]"
      layout="total, sizes, prev, pager, next, jumper"
      :total="tablePage.total">
    </el-pagination>
    <!--分页占位-->
    <!--    <div style="height: 34px;width: 100%" v-if="pageOut"></div>-->
    <beetles-table-transfer :drawer="drawer" @close-drawer="closeDrawer" :data="optionLabel"
                            :hide-list="hideList"
    ></beetles-table-transfer>
  </div>
</template>

<script>
import beetlesTableTransfer from "./beetles-table-transfer"
import tooltipText from "@/components/basic-components/tooltipText";
import crud from '@/util/crud'
import axios from 'axios'
import {validatenull} from "@/util/validate";


/**
 * 自定义组件未使用的功能 权限 permission
 *
 */

const VIEW_LIST_SHOW = 'view-list-show'
export default {
  components: {beetlesTableTransfer, tooltipText},
  name: "beetles-table",
  mixins: [crud()],
  props: {
    viewName: {

      type: String,
    },
    permission: {
      type: [Function, Object],
      default: () => {
        return {};
      }
    },
    option: {
      type: Object,
      default: () => {
        return {};
      }
    },
    tableLoading: {
      type: Boolean,
      default: false
    },
    page: {
      type: Object,
      default() {
        return {};
      }
    },
    data: {
      type: Array,
      required: true,
      default: () => {
        return [];
      }
    }
  },
  data() {
    return {
      headerOut: false,
      pageOut: false,
      top: '',
      left: '',
      headerHeight: '',
      width: '',
      right: '',
      drawer: false,
      io: null,
      tablePage: {},
      optionLabel: [],//列名称
      DIC: {},
      hideList: [],//隐藏列的名称
      list: [],
    }
  },
  computed: {
    cssTop() {
      return {
        "--top": this.top,
        "--width": this.width,
        "--left": this.left,
        "--right": this.right,
        "--height": this.headerHeight
      }
    },
    pageWidth() {
      return {
        "--width": this.width
      }
    }
  },
  watch: {
    page: {
      deep: true,
      handler(val) {
        this.tablePage = val
      }
    },
    data: {
      deep: true,
      handler() {
        this.dataInit();
      },
    },
    loading: {
      deep: true,
      handler(val) {
        this.load = val
      }
    }
  },
  created() {
    //初始化字典
    this.dicInit().then(() => {
      this.dataInit();
    });
    this.tablePage = this.page
    this.$emit('on-load', this.tablePage)
  },
  mounted() {
    this.scrollInit();
    this.fetchInit();
    // console.log('beetletable挂载了')
  },
  beforeDestroy() {
    //销毁监控
    window.removeEventListener('scroll', this.handleScroll, true)
  },
  activated() {
    // 解决组件 - keep-alive方式报错
    this.scrollInit();
  },
  deactivated() {
    // 解决组件 - keep-alive方式报错
    window.removeEventListener('scroll', this.handleScroll, true)
  },
  methods: {
    /**
     * 数据初始化
     */
    dataInit() {
      if (this.data && this.data.length > 0) {
        this.data.forEach((ele, index) => {
          this.$set(ele, '$index', index)
          this.localDic(this.option.column, index);
        })
      }
      this.tablePage = this.page
      this.list = this.data
      this.load = this.tableLoading
    },
    /**
     * 滑动初始化
     */
    scrollInit() {
      //滑动监控
      this.$nextTick(() => {
        // marco解决滚动出现表头影响其他页面
        var avueView = document.getElementById('avue-view')
        avueView.addEventListener('scroll', this.handleScroll, true)
        // window.addEventListener('scroll', this.handleScroll, true)
        this.$refs.beetlesTable.doLayout();
      });
    },
    /**
     * 显隐初始化
     */
    fetchInit() {
      //获取显隐的保存记录
      if (this.fetchWindow()) {
        this.hideList = new Map(this.fetchWindow()).get(this.viewName) || []
      }
    },
    /**
     * 初始化字典
     */
    async dicInit() {
      this.handleLoadDic(this.option.column);
    },
    /**
     * 列是否展示
     */
    columnShow(row) {
      if (this.hideList.length === 0 || this.hideList.findIndex(item => row.prop === item) >= 0) {
        if (row.showColumn === false) {
          return false
        }
        return true
      } else {
        return false
      }
    },
    /**
     * 监控滚动
     */
    handleScroll() {
      let tableView = document.getElementById('beetles_table').getBoundingClientRect()
      let tableHeader = this.$refs.beetlesTable.$refs.headerWrapper.getBoundingClientRect()
      this.headerHeight = tableHeader.height || this.headerHeight
      let headerSeat = document.getElementById('header-seat').getBoundingClientRect()
      let view = document.getElementById('avue-view').getBoundingClientRect()
      let screen = window.innerWidth
      // 表头没有浮动
      if (this.headerOut === false && tableHeader.bottom - view.top - (tableHeader.height / 2) < 0 && tableView.bottom - view.top >= 0) {  //过表头的中间点 并且 列表在可视范围
        this.headerOut = true
        this.top = view.top + 'px'
        this.width = tableView.width + 'px'
        this.left = tableView.left + 'px'
        this.right = screen - tableView.left - tableView.width + 'px'
      }
      //表头已经浮动
      if (headerSeat.bottom - view.top - (headerSeat.height / 2) > 0 && tableView.bottom - view.top >= 0) {  //过表头的中间点 并且 列表在可视范围
        this.headerOut = false
      }

      if (tableView.bottom >= view.top + view.height && tableView.bottom - view.top >= 0) {
        this.pageOut = true
        this.width = tableView.width + 'px';
      } else {
        this.pageOut = false
      }
    },
    /**
     * 修改表头样式
     * @param row
     * @param column
     * @param rowIndex
     * @param columnIndex
     * @returns {{padding: number, color: string, background: string, fontSize: string, opacity: number}|{padding: number, color: string, background: string, fontSize: string}}
     */
    changeTableCell() {
      let inHeader = {color: 'rgba(0, 0, 0, .85)', background: '#fafafa', fontSize: '12px'}
      let outHeader = {color: 'white', background: 'black', fontSize: '12px', opacity: 0.7}
      return this.headerOut ? outHeader : inHeader
    },
    /**
     * 切换分页
     */
    handleCurrentChange(currentPage) {
      this.$emit('current-change', currentPage)
      this.$emit('on-load', this.tablePage)
    },
    /**
     * 切换页面内容大小
     */
    handleSizeChange(sizePage) {
      this.$emit('size-change', sizePage)
      this.$emit('on-load', this.tablePage)
    },
    /**
     * 刷新列表
     */
    refreshChange() {
      this.$emit('refresh-change')
    },
    /**
     * 控制列显隐
     */
    showHide() {
      let hasShow = false
      if (this.fetchWindow()) {
        if (new Map(this.fetchWindow()).get(this.viewName))
          hasShow = true
      }
      this.optionLabel = []
      this.option.column.map(item => {
        this.optionLabel.push({
          key: item.prop,
          label: item.label
        })
        if (!hasShow) this.hideList.push(item.prop)
      })
      if (hasShow) this.hideList = new Map(this.fetchWindow()).get(this.viewName)
      this.drawer = true
    },
    /**
     *  关闭显隐
     */
    closeDrawer(value) {
      //确认显示的字段
      this.hideList = value
      let map = new Map()
      if (this.fetchWindow()) {
        map = new Map(this.fetchWindow())
      }
      map.set(this.viewName, value)
      this.saveWindow(map)
      //将内容保存到浏览器中
      this.drawer = false
    },
    /**
     * 保存到浏览器
     */
    saveWindow(map) {
      window.localStorage.setItem(VIEW_LIST_SHOW, JSON.stringify(map))
    },
    fetchWindow() {
      return JSON.parse(window.localStorage.getItem(VIEW_LIST_SHOW) || '0')
    },
    /**
     * 勾选项
     */
    selectionChange(rows) {
      this.$emit('selection-change', rows)
    },

    toggleSelection(rows) {
      if (rows) {
        rows.forEach(row => {
          this.$refs.beetlesTable.toggleRowSelection(row);
        });
      } else {
        this.$refs.beetlesTable.clearSelection();
      }
    },
    /**
     * 数据处理
     */
    translate(row, column) {
      let result = '';
      result = row['$' + column.prop] || row[column.prop]
      return result
    },
    /**
     * 本地字典加载
     */
    localDic(list, index) {
      list.map(item => {
        if (item.dicData) {
          this.displayValue(item, index)
        }
      })
    },

    /**
     * 在列表中添加翻译值
     */
    displayValue(v, index) {
      this.$set(this.data[index], '$' + v.prop, this.getDisplayValue(v, index))
    },

    /**
     * 获取翻译值
     */
    getDisplayValue(v, index) {
      let ind = v.dicData.findIndex(it => it[v.props ? v.props.value : 'value'] === this.data[index][v.prop])
      if (ind > -1) {
        return v.dicData[ind][v.props ? v.props.label : 'label']
      } else {
        return this.data[index][v.prop]
      }
    },

    /**
     * 网络字典加载
     */
    handleLoadDic(list) {
      let dicList = []
      let result = [];
      if (validatenull(list)) {
        return;
      }
      list.forEach((ele) => {
        if (ele.dicUrl) {
          result.push(new Promise(resolve => {
            if (!validatenull(ele.dicUrl)) {
              dicList.push(ele.prop)
              axios.get(`${ele.dicUrl}`).then(function (response) {
                resolve(validatenull(response.data.data) ? [] : response.data.data);
              })
            }
          }))
        }
      })
      Promise.all(result).then(data => {
        dicList.map((item, index) => {
          list[list.findIndex(it => it.prop === item)]['dicData'] = data[index]
        })
        this.data.map((item, index) => {
          this.localDic(this.option.column, index);
        })
      }).catch(err => {
        console.log(err)
      })
    },
    /**
     * 双击点击
     */
    rowDbclick(row, column, event) {
      this.$emit('row-dblclick', row, column, event)
    },
    /**
     * 单击点击
     */
    rowClick(row, column, event) {
      this.$emit('row-click', row, column, event)
    },
  }

}
</script>
<style lang="scss" scoped>

.beetles_table_menu {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: justify;
  -ms-flex-pack: justify;
  justify-content: space-between;
  position: relative;
  width: 100%;
  min-height: 40px;
  height: auto;
  overflow: hidden;
  margin-bottom: 5px;
  background-color: #fff;

  .beetles_table_left {
    justify-items: flex-start;
    display: flex;
    align-items: center;
  }

  .beetles_table_right {
    justify-items: flex-end;
    display: flex;
    align-items: center;
  }
}

/deep/ .header-out {
  .el-table__header-wrapper {
    position: fixed;
    overflow: hidden;
    width: var(--width) !important;
    top: var(--top);
    z-index: 400;
    opacity: 0.8;
  }

  .el-table__body-wrapper {
    margin-top: var(--height);
  }

  .el-table__fixed {
    .el-table__fixed-header-wrapper {
      position: fixed;
      overflow: hidden;
      top: var(--top);
      width: var(--width);
      left: var(--left);
      z-index: 405;

      .is-hidden {
        visibility: hidden;
      }
    }

    .el-table__fixed-body-wrapper {
      top: 0 !important;
    }
  }

  .el-table__fixed-right {
    .el-table__fixed-header-wrapper {
      position: fixed;
      display: flex;
      justify-content: flex-end;
      width: var(--width);
      top: var(--top);
      right: var(--right);
      z-index: 403;

      .is-hidden {
        visibility: hidden;
        width: 0;
      }
    }

    .el-table__fixed-body-wrapper {
      top: 0 !important;
    }
  }

}

.table {
  line-height: 23px;
  font-size: 12px !important;

  /deep/ .el-table__body {
    width: 100% !important;
  }

  /deep/ .el-table__header {
    width: 100% !important;
  }
}

.beetles_table_page {
  margin-top: 1em;
  display: flex;
  justify-content: right;
  margin-bottom: 1em;
}

.beetles_table_out_page {
  position: fixed;
  bottom: 3px;
  display: flex;
  z-index: 8;
  padding: 3px 10px;
  box-sizing: border-box;
  justify-content: right;
  width: var(--width);
  color: white;
  background: black;

  /deep/ .el-pagination__total {
    color: white;
  }

  /deep/ .el-pagination__jump {
    color: white;
  }
}

//author:marco 多选框框偏左边问题
/deep/ .el-table-column--selection {
  .cell {
    padding: unset!important;
    text-align: center;
  }
}

</style>
